package de.hhn.mim.psb;


/**
 * Klasse definiert einen dreidimensionalen Vektor mit den Elementen
 * x, y und z und einige wichtige Vektoroperationen:
 * Addition
 * Subtraktion
 * norm und normalize (a: berechnet den Betrag, b: normiert Komponenten)
 * Skalar/Dot-Produkt: scalarProduct und dotProduct
 * Aeusseres bzw. Kreuz-Produkt: outerProduct und crossProduct
 * Mittelwert (mean) und RMS (rms) fuer Arrays von Vektoren
 * equals vergleicht zwei Vektoren und equals_print gibt das Ergebnis in
 * der Console aus.
 * Verschiedene print Funtkionen
 * 
 * @author Rolf Bendl
 * 
 * 2012-05-12: Klasse erstellt
 * 2014-02-05: 
 * Fehler in rms, von den Werten wurde jeweils der Mittelwert abgezogen,
 * also die Standardabweichung und nicht RMS berechnet
 * 
 */
public class Vect3D
 {
  double x;
  double y;
  double z;
  
  public Vect3D() {x = 0; y = 0; z = 0;}
  public Vect3D(double x, double y, double z) 
   {
    this.x = x;
    this.y = y;
    this.z = z;
   }
  public Vect3D(Vect3D v)
   {
    this.x = v.x;
    this.y = v.y;
    this.z = v.z;
   }
  public Vect3D addVect(Vect3D v)
   {
    Vect3D result = new Vect3D();
    result.x = x + v.x;
    result.y = y + v.y;
    result.z = z + v.z;
    return result;
   }
  
  public Vect3D subtractVect(Vect3D v)
   {
    Vect3D result = new Vect3D();
    result.x = x - v.x;
    result.y = y - v.y;
    result.z = z - v.z;
    return result;
   }
  
  public double norm()
   {
    return Math.sqrt(x*x + y*y + z *z);
   }
  
  public Vect3D normalize()
   {
    Vect3D result = new Vect3D();
    double length = norm();
    result.x = x / length;
    result.y = y / length;
    result.z = z / length;
    return result;
   }
  public double dotProduct(Vect3D v)
   {
    return scalarProduct(v);
   }
  public double scalarProduct(Vect3D v)
   {
    double result = 0;
    result = x * v.x + y * v.y + z * v.z;
    return result;    
   }
  public Vect3D outerProduct(Vect3D v)
   {
    return crossProduct(v);
   }
  public Vect3D crossProduct(Vect3D v)
   {
    Vect3D result = new Vect3D();
    result.x = y * v.z - z * v.y; 
    result.y = z * v.x - x * v.z;
    result.z = x * v.y - y * v.x;  
    return result;    
   }
  
  public static Vect3D mean(Vect3D [] points)
   {
    Vect3D mean = new Vect3D();
    for(int i = 0; i < points.length; i++)
     {
      mean.x = mean.x + points[i].x; 
      mean.y = mean.y + points[i].y; 
      mean.z = mean.z + points[i].z; 
     }
    mean.x = mean.x / (double) points.length;
    mean.y = mean.y / (double) points.length;
    mean.z = mean.z / (double) points.length;
    return mean;
   }
  
  public static Vect3D rms(Vect3D [] points)
   {
    int print = 1;
    Vect3D rms  = new Vect3D();
    
    if(print > 0) System.out.println("in Vect3D.rms");
    for(int i = 0; i < points.length; i++)
     {
      Vect3D help = new Vect3D();
      help.x = (points[i].x);
      rms.x  = rms.x + help.x * help.x;
      help.y = (points[i].y);
      rms.y  = rms.y + help.y * help.y;
      help.z = (points[i].z);
      rms.z  = rms.z + help.z * help.z;
      if(print > 1)
       {
        points[i].print("point[" + i + "]");
        rms.print("sum of components^2");
       }
     }
    rms.x = rms.x / (double) points.length;    
    rms.y = rms.y / (double) points.length;    
    rms.z = rms.z / (double) points.length;    
    if(print > 0) rms.print("rms2");
    rms.x = Math.sqrt(rms.x);    
    rms.y = Math.sqrt(rms.y);    
    rms.z = Math.sqrt(rms.z);    
    if(print > 0) rms.print("rms ");
    
    return rms;
    
    
   }
  boolean equals(Vect3D v)
   {
    boolean result = true;
    double  epsilon = 0.0002;
    double  diff_x = Math.abs(x - v.x);
    double  diff_y = Math.abs(y - v.y);
    double  diff_z = Math.abs(z - v.z);
    if(diff_x > epsilon)      result = false;
    else if(diff_y > epsilon) result = false;
    else if(diff_z > epsilon) result = false;
    return result;
   }
  boolean equals_print(String label, Vect3D v)
   {
    boolean result = true;
    double  epsilon = 0.0002;
    double  diff_x = Math.abs(x - v.x);
    double  diff_y = Math.abs(y - v.y);
    double  diff_z = Math.abs(z - v.z);
    if(diff_x > epsilon)      result = false;
    else if(diff_y > epsilon) result = false;
    else if(diff_z > epsilon) result = false;
    if(true)
     {
      System.out.printf(label + ": v1.x %7.2f y %7.2f z %7.2f    v2.x %7.2f y %7.2f z %7.2f diff_x %7.2f y %7.2f z %7.2f \n", 
                        x, y, z, v.x, v.y, v.z, diff_x, diff_y, diff_z);
     }
    return result;
   }
  public void print()
   {
    System.out.printf("x %7.2f y %7.2f z %7.2f\n", x, y, z);    
   }
  public void print(String label)
   {
    System.out.print(label + ":    ");
    print();
   }
  public static void print(String label, Vect3D v1, Vect3D v2, Vect3D v3)
   {
    System.out.print(label + ": ");
    System.out.printf("v1.x %7.2f y %7.2f z %7.2f    v2.x %7.2f y %7.2f z %7.2f   v3.x %7.2f y %7.2f z %7.2f\n", 
                      v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, v3.x, v3.y, v3.z);    
//    System.out.printf("v2.x %7.2f  y %7.2f  z %7.2f   v3.x  %7.2f  y %7.2f  z %7.2f\n", 
//                      v2.x, v2.y, v2.z, v3.x, v3.y, v3.z);    
    
   }
 }

